package vmi.surgis;

import android.graphics.Matrix;
import android.graphics.PointF;
import android.util.FloatMath;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.GestureDetector.SimpleOnGestureListener;

public class MapGestureListener extends SimpleOnGestureListener
{
	// These matrices will be used to move and zoom image
	SURGISActivity parent;
	Matrix mapMatrix 	  = new Matrix();
	// Matrix mapMatrixSaved = new Matrix();
	MapView map; 
	
	GestureDetector gestureScanner;
	
	// We can be in one of these 3 states
    static final int NONE = 0;
    static final int ZOOM = 1;
    int mode = NONE;
    
    float distanceOld;
	PointF midPoint = new PointF();
	
	public MapGestureListener(SURGISActivity act, MapView aMap)
	{
		parent = act;
		map = aMap;
		gestureScanner = new GestureDetector(this);
	}

	private float spacing(MotionEvent event) {
	   float x = event.getX(0) - event.getX(1);
	   float y = event.getY(0) - event.getY(1);
	   return FloatMath.sqrt(x * x + y * y);
	}
	private void getMidPoint(PointF point, MotionEvent event) {
	  float x = event.getX(0) + event.getX(1);
	  float y = event.getY(0) + event.getY(1);
	  point.set(x / 2, y / 2);
	}
	
	public boolean onTouchEvent(MotionEvent event)
	{	
		switch (event.getAction() & MotionEvent.ACTION_MASK)
		{
		   case MotionEvent.ACTION_UP:
		   case MotionEvent.ACTION_POINTER_UP:
		      mode = NONE;
		      Log.d(null, "mode=NONE" );
		      break;		      
		   case MotionEvent.ACTION_POINTER_DOWN:
			   return onPinch(event, spacing(event));			   
		   case MotionEvent.ACTION_MOVE:
			  if (mode == ZOOM) {
		    	 return onPinchZoom(event, spacing(event));
		      }
		      break;
		}
		return gestureScanner.onTouchEvent(event);
	}
	
	public boolean onPinch(MotionEvent event, float distance)
	{
		if (distance > PINCH_MIN_DISTANCE)
		{
			distanceOld = distance;
			getMidPoint(midPoint, event);
			mode = ZOOM;
			Log.d(null, "mode=ZOOM" );
			return true;
		}
		return false;
	}
	
	public boolean onPinchZoom(MotionEvent event, float distance)
	{
		//Log.d(null, "newDist=" + distance);
		if (distance > PINCH_MIN_DISTANCE)
		{
			float scale = distance / distanceOld;
			map.Zoom(scale, midPoint);
			return true;
		}
		return false;
	}
	
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
	{
		map.Scroll(distanceX, distanceY);			
		// Log.w(null, "Scroll!");
		return true;
	}
	
	private static final float PINCH_MIN_DISTANCE = 10f;
	private static final int SWIPE_MIN_DISTANCE = 12;
	private static final int SWIPE_THRESHOLD_VELOCITY = 20;
	
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
		// Log.w(null, "Fling!");
		
		if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
            return false; // Right to left
        }  else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
            return false; // Left to right
        }
        if(e1.getY() - e2.getY() > SWIPE_MIN_DISTANCE && Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY) {
            return false; // Bottom to top
        }  else if (e2.getY() - e1.getY() > SWIPE_MIN_DISTANCE && Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY) {
            return false; // Top to bottom
        }
        return false;
    }

	public boolean onDown(MotionEvent event) {
		parent.resetTextField();
    	parent.resetFocus();
		return false;
	}

	public void onLongPress(MotionEvent event) {
		if (mode == NONE)
		{
			parent.openContextMenu(map.map);
			map.selectedPos = new PointF(event.getX(), event.getY());
		}
	}

	public void onShowPress(MotionEvent event) {
		// TODO Auto-generated method stub
		
	}

	public boolean onSingleTapUp(MotionEvent event) {
    	return false;
	}
}
